from django.db import models
from ideavolution.settings import IDEA_MEDIA_PATH
import hashlib
from django.contrib import admin


class IdeaBase(models.Manager):
    def all(self):
        b = Idea.objects.filter(parent=None)
        return b

class IdeaHash(models.Manager):
    def md5(self):
        ideas = Idea.objects.all().order_by('id')
        hash_list = {}
        
        for i in ideas:
            hash_list[i.md5] = i
            
        return hash_list
    
class IdeaConnections(models.Manager):
    def hierarchy(self):
        conns = {}
        bases = Idea.base.all()
        for b in bases:
            conns.update(self._get_children_connections(b))
        return conns
    
    def user(self):
        conns = Connection.objects.all()
        hash_list = {}
        
        for c in conns:
            hash_list[c.md5] = c
            
        return hash_list
    
    def infer(self):
        return {}
    
    def all(self):
        conns = {}
        #conns.update(self.hierarchy())
        conns.update(self.user())
        conns.update(self.infer())
        return conns
    
    def _get_children_connections(self, idea):
        conns = {}
        if idea.children.count() != 0:
            for c in idea.children.all():
                conns.update(self._get_children_connections(c))
            return conns
        elif idea.parent:
            c = Connection(id=0, from_idea=idea.parent, to_idea=idea, strength=1)
            return [(str(c.md5), c)]
        else:
            return []

class Content(models.Model):
    """
    Content is a container for text and graphics for ideas or connections.
    
    title -> 100 character or less string describing the title
    text -> a larger string for the contents of an entry
    link -> a link to an external file (image, etc.) containing an idea
    """
    title = models.CharField(max_length=100, null=True, blank=True)
    text = models.TextField(null=True, blank=True)
    link = models.FileField(upload_to=IDEA_MEDIA_PATH, null=True, blank=True)
    
class Idea(models.Model):
    """
    Idea is the container that holds a concept over the course of its evolution.
    It is organized in a tree structure and has a sense of its content and originator.
    
    parent -> a reference to the parent Idea
    content -> a reference to the Content object that contains the current iteration of the idea
    """
    parent = models.ForeignKey('self', null=True, blank=True, related_name='child_set')
    title = models.CharField(max_length=100, null=True, blank=True)
    text = models.TextField(null=True, blank=True)
    connection_set = models.ManyToManyField('self', through="Connection", symmetrical=False, null=True, blank=True)
    size = models.FloatField(null=True, blank=True)
    
    objects = models.Manager()
    hashes = IdeaHash()
    base = IdeaBase()
    
    def _get_children(self):
        return self.child_set.all()
    children = property(_get_children)
    
    def _get_siblings(self):
        try:
            return Idea.objects.filter(parent__id = self.parent.id).exclude(id = self.id)
        except AttributeError: # No parent because it is the root
            return Idea.objects.none()
    siblings = property(_get_siblings)
    
    """def _get_connections(self):
        return self.connection_set.all()
    connections = property(_get_connections)"""
    
    def _get_MD5(self):
        m = hashlib.md5()
        m.update("%d%s%s%d" %(self.id, self.title, self.text, self.size));
        return m.digest()
    md5 = property(_get_MD5)
    
    def __str__(self):
        if self.parent:
            return '%d --> %d' %(self.id, self.parent.id)
        else:
            return '%d' %(self.id)
    
    class Meta:
        ordering = ['id']
        
class Connection(models.Model):
    from_idea = models.ForeignKey(Idea, null=True, blank=True, related_name="links_from")
    to_idea = models.ForeignKey(Idea, null=True, blank=True, related_name="links_to")
    strength = models.FloatField(null=True, blank=True)
    
    objects = models.Manager()
    links = IdeaConnections()

    def _get_MD5(self):
        m = hashlib.md5();
        m.update("%d%d" %(self.id, self.strength));
        return m.digest()
    md5 = property(_get_MD5)